﻿// ***********************************************************************
// Assembly         : Delta_webrender
// Author           : Juan Alberto Cerino Gomez
// Created          : 04-12-2013
//
// Last Modified By : Juan Alberto Cerino Gomez
// Last Modified On : 05-28-2013
// ***********************************************************************
// <copyright file="TablaUI.cs" company="Delta Bussines">
//     Copyright (c) 2013  Delta Bussines. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using Delta_util.Clases;
using System.Reflection;
using System.Collections;
using Delta_entidad.Atributos;
using Delta_entidad.EntidadesControl;
using Delta_entidad.Base;
using Delta_util.Estaticos;

namespace Delta_webrender.Dynamic
{
    /// <summary>
    /// Clase que se encarga de generar el formulario de captura para una entidad configurada, de forma automatica.
    /// </summary>
    [Serializable()]
    public class TablaUI
    {

        /// <summary>
        /// Estructura de datos basica que contiene un valor y una descripción.
        /// </summary>
        public struct DatosClave
        {
            /// <summary>
            /// Texto del dato.
            /// </summary>
            private string _texto;
            /// <summary>
            /// Valor.
            /// </summary>
            private string _valor;

            /// <summary>
            /// Obtiene o establece el texto.
            /// </summary>
            /// <value>Texto.</value>
            public string texto
            {
                get { return _texto; }
                set { _texto = value; }
            }


            /// <summary>
            /// Obtiene o establece el valor.
            /// </summary>
            /// <value>Valor.</value>
            public string valor
            {
                get { return _valor; }
                set { _valor = value; }
            }

        }


        #region Declaraciones
        /// <summary>
        /// Variable que guarda el contenedor donde se dibujarán los componentes.
        /// </summary>
        protected string _contenedor;
        /// <summary>
        /// Variable que guarda los valores por default, los cuales se assignan la primera vez que se pinta un componente.
        /// </summary>
        protected Dictionary<string, object> _valoresDefault = null;
        /// <summary>
        /// Variable que guarda la configuración dinamica configurada OnLine para el tipo especificado.
        /// </summary>
        protected List<dynamic> _configUsers = null;
        /// <summary>
        /// Lista de componentes personalizados por el usuario.
        /// </summary>
        protected List<Control> _controlesPersonalizados = null;
        /// <summary>
        /// El tipo de dato al cual se le va a crear el formulario de captura.
        /// </summary>
        protected Type _tipo = null;
        /// <summary>
        /// Listado de los campos a dibujar, despues de aplicar ciertos filtros a la configuración dinamica y de la entidad.
        /// </summary>
        protected List<Cat_campo_tecnico> camposDibujar = new List<Cat_campo_tecnico>();
        /// <summary>
        /// Componente en donde se realiza la busqueda de los controles personalizados por el usuario. 
        /// </summary>
        protected Control _ObjetoPadre = null;
        #endregion

        #region Delegados y eventos
        /// <summary>
        /// Delegado que se usa para indicar si un atributo debe ser dibujado o no en el formulario, esta validación solo se aplica a los campos que solo tienen configuracion en la clase.
        /// </summary>
        /// <param name="atributo">Atributo que representa la configuración basica del campo.</param>
        /// <param name="atributoEditor">Atributo que representa la configuración del tipo de editor.</param>
        /// <param name="atributoTipo">Atributo que representa la configuración de la clase entidad.</param>
        /// <param name="atributoFiltro">Atributo que representa a configuración de filtro de datos.</param>
        /// <param name="atributoEditorFiltro">Atributo que representa a configuración del editor que se quiere mostrar en el panel de filtro.</param>
        /// <returns>Valor que indica si se debe dibujar o no el campo.</returns>
        public delegate bool delDibujarDatosAtributo(AttPropiedad atributo, AttEditor atributoEditor, AttTipo atributoTipo, AttFiltro atributoFiltro, AttEditorFiltro atributoEditorFiltro);
        /// <summary>
        /// Delegado que se usa para indicar si un atributo debe ser dibujado o no en el formulario, esta validación solo se aplica a los campos que tienen configuración OnLine.
        /// </summary>
        /// <param name="datos">Los datos de la configuración dinamica de los datos.</param>
        /// <returns>Valor que indica si se debe dibujar o no el campo.</returns>
        public delegate bool delDibujarDatosConfig(Cat_campo_tecnico datos);
        /// <summary>
        /// Variable que permite configurar la expresion a usar para indicar si un campo no configurado OnLine, se debe pintar.
        /// </summary>
        public delDibujarDatosAtributo ValidacionDibujarAtributo;
        /// <summary>
        /// Variable que permite configurar la expresion a usar para indicar si un campo configurado OnLine, se debe pintar.
        /// </summary>
        public delDibujarDatosConfig ValidacionDibujarConfig;
        #endregion

        #region Propiedades
        /// <summary>
        /// Obtiene o establece los datos de la entidad a representar, si no es null,se leen los datos de la entidad y se escriben en los componentes.
        /// </summary>
        /// <value>Entidad que hereda TipoBase que contiene los datos a visualizar.</value>
        public TipoBase Entidad { get; set; }
        /// <summary>
        /// Obtiene o establece el componente que contiene los componentes personalizados que se van a enlazar con los campos.
        /// </summary>
        /// <value>Componente padre.</value>
        public Control ObjetoPadre { get { return _ObjetoPadre; } set { _ObjetoPadre = value; } }
        /// <summary>
        /// Obtiene o establece los valores por default configurados por el usuario.
        /// </summary>
        /// <value>IDictionary con los valores defualt.</value>
        public Dictionary<string, object> valoresDefault { get { return _valoresDefault; } set { _valoresDefault = value; } }
        /// <summary>
        /// Obtiene o estable la configuración user del tipo al cual se le dibuja el fomurlario.
        /// </summary>
        /// <value>Lista de configuración dinamica, representada como Lista dinamica.</value>
        public List<dynamic> configUsers { get { return _configUsers; } set { _configUsers = value; } }
        /// <summary>
        /// Obtiene o establece la lista de campos a dibujar, de acuerdo a los atributos configurados en la entidad y la configuración OnLine especificada al tipo.
        /// </summary>
        /// <value>Lista de configuración.</value>
        public List<Cat_campo_tecnico> listaCamposDibujar { get { return camposDibujar; } }
        /// <summary>
        /// Obtiene o establece los controles personalizados por el usuario, los cuales se va a enlazar con los campos del tipo especificado.
        /// </summary>
        /// <value>Lista de controles o componentes personalizados.</value>
        public List<Control> controlesPersonalizados { get { return _controlesPersonalizados; } set { _controlesPersonalizados = value; } }
        /// <summary>
        /// Obtiene o establece el nombre del contenedor en el cual se va a dibujar el formulario.
        /// </summary>
        /// <value>Nombre del contenedor.</value>
        public string contenedor
        {
            get
            {
                if (_contenedor == null)
                    return "";
                else
                    return _contenedor;
            }
            set { _contenedor = value; }
        }
        /// <summary>
        /// Obtiene o establece el tipo de dato al cual se le va a crear el formulario.
        /// </summary>
        /// <value>Tipo de la entidad, este tipo debe heredar a TipoBase.</value>
        public Type tipo
        {
            get { return _tipo; }
            set
            {
                _tipo = value;
                camposDibujar.Clear();
                if (value != null)
                {
                    foreach (System.Reflection.PropertyInfo propiedad in tipo.GetProperties())
                    {
                        if (!Comun.PropiedadDinamica(propiedad.Name, configUsers))
                        {

                            AttPropiedad atributo = Comun.ObtenerAtributoEntidad<AttPropiedad>(tipo, propiedad);
                            AttrParametro atributoParametro = Comun.ObtenerAtributoEntidad<AttrParametro>(tipo, propiedad);
                            AttEditor atributoEditor = Comun.ObtenerAtributoEntidad<AttEditor>(tipo, propiedad);
                            AttTipo atributoTipo = Comun.ObtenerAtributoEntidad<AttTipo>(tipo, propiedad);
                            AttFiltro atributoFiltro = Comun.ObtenerAtributoEntidad<AttFiltro>(tipo, propiedad);
                            AttEditorFiltro atributoEditorFiltro = Comun.ObtenerAtributoEntidad<AttEditorFiltro>(tipo, propiedad);
                            bool dibujar = false;
                            if (ValidacionDibujarAtributo == null)
                                dibujar = atributo != null && atributo.editable;
                            else
                                dibujar = ValidacionDibujarAtributo.Invoke(atributo, atributoEditor, atributoTipo, atributoFiltro, atributoEditorFiltro);
                            if (dibujar)
                            {
                                Cat_campo_tecnico ncampo = atributo.datos_campo;
                                ncampo.nombre = propiedad.Name;
                                if (atributoEditor != null)
                                    Comun.RellenarEntidadSinNULL(atributoEditor.editor, ncampo.tipo_editor);

                                if (atributoTipo != null)
                                    Comun.RellenarEntidadSinNULL(atributoTipo.tipo, ncampo.tipo);

                                if (atributoFiltro != null)
                                    ncampo.filtro = atributoFiltro.filtro;

                                if (atributoEditorFiltro != null)
                                    ncampo.editorFiltro = atributoEditorFiltro.editor;
                                if (atributoParametro != null)
                                {
                                    string[] infoTipoBD = (atributoParametro as dynamic).propTipoDato.ToString().Split('.');
                                    ncampo.tipo.tipo_bd = infoTipoBD[infoTipoBD.Length - 1].ToUpper();
                                    if (ncampo.tipo.tipo_bd.Contains("CHAR") || ncampo.tipo.tipo_bd.Contains("TEXT"))
                                    {
                                        ncampo.tipo.tipo_bd += "(" + atributoParametro.propPrecision.ToString() + ")";
                                        ncampo.tamanio = (Int16)atributoParametro.propPrecision;
                                    }
                                }
                                else
                                    ncampo.tipo.tipo_bd = "Varchar";
                                ncampo.nombre = propiedad.Name;
                                camposDibujar.Add(atributo.datos_campo);
                            }
                        }
                    }
                }
                if (configUsers != null)
                {
                    foreach (dynamic datosUser in configUsers)
                    {
                        bool dibujar = false;
                        if (ValidacionDibujarConfig == null)
                            dibujar = datosUser.editable;
                        else
                            dibujar = ValidacionDibujarConfig.Invoke(datosUser);

                        if (dibujar)
                            camposDibujar.Insert(0, datosUser);
                    }
                }

            }

        }
        #endregion
        /// <summary>
        /// Metodo que se encarga de rellenar una entidad a partir de un formulario dibujado por esta clase.
        /// </summary>
        /// <param name="ctrlWeb">El control web del cual se obtiene el dato.</param>
        /// <param name="entidad">Entidad en la cual se guarda el valor obtenido.</param>
        /// <param name="propConfig">Propiedad del control web de la cual se obtiene el valor, si es null, el nombre de la propiedad se lee de la configuración del campo.</param>
        /// <param name="tag">El tag que señala que el control web es dinamico y configurado por esta clase.</param>
        protected internal void RellenarEntidadWeb(Control ctrlWeb, dynamic entidad, string propConfig = null, string tag = "wcontrol")
        {
            if (ctrlWeb is LiteralControl || ctrlWeb.ID == null)
                return;
            if (ctrlWeb.ID.Contains(tag))
            {
                string[] datoscontrol = ctrlWeb.ID.Split('|');
                object valor = null;
                var busqueda = from campo in camposDibujar where campo.nombre == datoscontrol[2] select campo;
                if (busqueda == null || busqueda.Count() == 0)
                    return;
                Cat_campo_tecnico datosCampo = busqueda.First();


                if (!string.IsNullOrWhiteSpace(propConfig))
                    valor = Comun.GetValorControlWeb(ctrlWeb, propConfig);
                else
                {
                    valor = Comun.GetValorControlWeb(ctrlWeb, datosCampo.tipo_editor.propiedad_valor);


                }

                Type tipoPropiedad = Comun.ObtenerTipoPropiedad(entidad, datosCampo.nombre);
                if (valor != null && valor is string && string.IsNullOrWhiteSpace(valor.ToString()) && tipoPropiedad != null)
                    valor = Comun.ObtenerDefaultTipo(tipoPropiedad);
                entidad.FijarValor(datosCampo.nombre, valor);
            }
        }

        /// <summary>
        /// Se encarga de limpiar los datos de un control web.
        /// </summary>
        /// <param name="ctrlWeb">El control web que se desea limpiar los datos.</param>
        /// <param name="entidad">Entidad que se está representando en el formulario.</param>
        /// <param name="propConfig">Propiedad del control web que se va a limpiar, si es null, el nombre de la propiedad se lee de la configuración del campo.</param>
        /// <param name="tag">El tag que señala que el control web es dinamico y configurado por esta clase.</param>
        private void LimpiarControlWeb(Control ctrlWeb, TipoBase entidad, string propConfig = null, string tag = "wcontrol")
        {
            if (ctrlWeb is DropDownList)
            {
                (ctrlWeb as DropDownList).ClearSelection();
                return;
            }


            if (ctrlWeb is LiteralControl || ctrlWeb.ID == null)
                return;
            string[] datoscontrol = ctrlWeb.ID.Split('|');
            if (!ctrlWeb.ID.Contains(tag))
                return;
            var busqueda = from campo in camposDibujar where campo.nombre == datoscontrol[2] select campo;
            if (busqueda == null || busqueda.Count() == 0)
                return;
            Cat_campo_tecnico datosCampo = busqueda.First();
            PropertyInfo propControl = ctrlWeb.GetType().GetProperty(datosCampo.tipo_editor.propiedad_valor);

            if (entidad.ExisteCampo(datosCampo.nombre))
                Comun.SetValorControlWeb(ctrlWeb, datosCampo.tipo_editor.propiedad_valor, Comun.ObtenerDefaultTipo(propControl.DeclaringType));
            //Comun.SetValorControlWeb(ctrlWeb, datosCampo.tipo_editor.propiedad_valor, entidad.ObtenerValor(datosCampo.nombre));


        }

        /// <summary>
        /// Metodo que se encarga de asignar valor a un control web.
        /// </summary>
        /// <param name="ctrlWeb">El control web al cual se le va asignará el dato.</param>
        /// <param name="entidad">La entidad de la cual se va a leer el valor para asignarlo al control web.</param>
        /// <param name="propConfig">Propiedad del control web a la cual se le asignará el valor, si es null, el nombre de la propiedad se lee de la configuración del campo.</param>
        ///<param name="validarCampo">Parametro que indica si el campo debe de validarse en la lista de configuración dinamica.</param> 
        ///<param name="nombre_campo">Nombre de la propiedad de la cual se toma el valor, esto se usa cuando no se valida el campo</param>
        /// <param name="tag">El tag que señala que el control web es dinamico y configurado por esta clase.</param>
        private void RellenarControlWeb(Control ctrlWeb, TipoBase entidad, string propConfig = null, string tag = "wcontrol", bool validarCampo = true, string nombre_campo = null)
        {
            Cat_campo_tecnico datosCampo = null;
            if (validarCampo)
            {
                if (ctrlWeb is LiteralControl || ctrlWeb.ID == null)
                    return;
                string[] datoscontrol = ctrlWeb.ID.Split('|');
                if (!ctrlWeb.ID.Contains(tag))
                    return;
                var busqueda = from campo in camposDibujar where campo.nombre == datoscontrol[2] select campo;
                if (busqueda == null || busqueda.Count() == 0)
                    return;
                datosCampo = busqueda.First();
            }

            //PropertyInfo prop = Utilerias.ObtenerPropiedadXNombre(entidad.GetType(), datosCampo.nombre);
            if (entidad.ExisteCampo(validarCampo ? datosCampo.nombre : nombre_campo))
                Comun.SetValorControlWeb(ctrlWeb, validarCampo ? datosCampo.tipo_editor.propiedad_valor : propConfig, 
                    entidad.ObtenerValor(validarCampo ? datosCampo.nombre : nombre_campo),datosCampo.tipo_editor.grid_formato);


        }

        /// <summary>
        /// Metodo que se encarga de asignar valor a un control web personalizado por el usuario.
        /// </summary>
        /// <param name="tbCaptura">Control web personalizado por el usuario.</param>
        /// <param name="entidad">Entidad que contiene los datos actuales.</param>
        public void RellenarControl(Control tbCaptura, dynamic entidad)
        {


            if (tbCaptura is Table)
                return;
            foreach (Control ctrlWeb in tbCaptura.Controls)
            {
                string PropValor = null;
                bool validarPropiedad = true;
                string campo = null;
                if (ctrlWeb is WebControl && (ctrlWeb as WebControl).Attributes["data-ValidarPropiedad"] != null)
                    validarPropiedad = Comun.Convertir<bool>((ctrlWeb as WebControl).Attributes["data-ValidarPropiedad"]);


                if (!validarPropiedad)
                    campo = Comun.Convertir<string>((ctrlWeb as WebControl).Attributes["campoFuente"]);

                if (ctrlWeb is WebControl && (ctrlWeb as WebControl).Attributes["data-DataValue"] != null)
                    PropValor = (ctrlWeb as WebControl).Attributes["data-DataValue"];
                if (ctrlWeb is UpdatePanel)
                {
                    foreach (Control ctrl in (ctrlWeb as UpdatePanel).ContentTemplateContainer.Controls)
                        RellenarControlWeb(ctrl, entidad, null, "wcontrol", validarPropiedad, campo);
                }
                else
                    RellenarControlWeb(ctrlWeb, entidad, PropValor, "wcontrol", validarPropiedad, campo);

                if (ctrlWeb.HasControls())
                    RellenarControl(ctrlWeb, entidad);
            }

        }

        /// <summary>
        /// Limpia todos los controles web dinamicos que contiene una tabla, configurada por esta clase.
        /// </summary>
        /// <param name="tbCaptura">La tabla que contiene los controles web.</param>
        /// <param name="entidad">Entidad que tiene los datos actuales.</param>
        /// <param name="tag">El tag que señala que el control web es dinamico y configurado por esta clase.</param>
        public void LimpiarTabla(Table tbCaptura, dynamic entidad, string tag = "wcontrol")
        {

            foreach (TableRow tb in tbCaptura.Rows)
                foreach (TableCell celda in tb.Cells)
                    foreach (Control ctrlWeb in celda.Controls)
                    {
                        if (ctrlWeb is UpdatePanel)
                        {
                            foreach (Control ctrl in (ctrlWeb as UpdatePanel).ContentTemplateContainer.Controls)
                                LimpiarControlWeb(ctrl, entidad, null, tag);
                        }
                        else
                            LimpiarControlWeb(ctrlWeb, entidad, null, tag);

                    }
        }

        /// <summary>
        /// Se encarga de presentar los datos de la entidad en el formulario creado dinamicamente.
        /// </summary>
        /// <param name="tbCaptura">La tabla que contiene los controles web.</param>
        /// <param name="entidad">Entidad que tiene los datos actuales.</param>
        /// <param name="tag">El tag que señala que el control web es dinamico y configurado por esta clase.</param>
        public void RellenarTabla(Table tbCaptura, dynamic entidad, string tag = "wcontrol")
        {

            foreach (TableRow tb in tbCaptura.Rows)
                foreach (TableCell celda in tb.Cells)
                    foreach (Control ctrlWeb in celda.Controls)
                    {
                        if (ctrlWeb is UpdatePanel)
                        {
                            foreach (Control ctrl in (ctrlWeb as UpdatePanel).ContentTemplateContainer.Controls)
                                RellenarControlWeb(ctrl, entidad, tag);
                        }
                        else
                            RellenarControlWeb(ctrlWeb, entidad, tag);

                    }
        }

        /// <summary>
        /// Se encarga de rellenar una entidad apartir de un control personalizado por el usuario, es decir un control que no se creó usando esta clase.
        /// </summary>
        /// <param name="tbCaptura">La tabla que contiene los controles web.</param>
        /// <param name="entidad">Entidad que tiene los datos actuales y en la cual se va a escribir el valor.</param>
        /// <param name="tag">El tag que señala que el control web es dinamico y configurado por esta clase.</param>
        public void RellenarEntidadControl(Control tbCaptura, ref dynamic entidad, string tag = "wcontrol")
        {


            if (tbCaptura is Table)
                return;
            foreach (Control ctrlWeb in tbCaptura.Controls)
            {
                string PropValor = null;
                if (ctrlWeb is WebControl && (ctrlWeb as WebControl).Attributes["data-DataValue"] != null)
                    PropValor = (ctrlWeb as WebControl).Attributes["data-DataValue"];
                if (ctrlWeb is UpdatePanel)
                {
                    foreach (Control ctrl in (ctrlWeb as UpdatePanel).ContentTemplateContainer.Controls)
                        RellenarEntidadWeb(ctrl, entidad, PropValor, tag);
                }
                else
                    RellenarEntidadWeb(ctrlWeb, entidad, PropValor, tag);

                if (ctrlWeb.HasControls())
                    RellenarEntidadControl(ctrlWeb, ref entidad, tag);
            }

        }



        /// <summary>
        /// Rellena automaticamente una entidad a partir de un formulario dinamico creado por esta clase.
        /// </summary>
        /// <param name="tbCaptura">La tabla que contiene los controles web.</param>
        /// <param name="entidad">Entidad que tiene los datos actuales y en la cual se va a escribir el valor.</param>
        /// <param name="tag">El tag que señala que el control web es dinamico y configurado por esta clase.</param>
        /// <param name="ejecutarMetodoGuardar">if set to <c>true</c> [ejecutar metodo guardar].</param>
        public void RellenarEntidad(Table tbCaptura, ref dynamic entidad, string tag = "wcontrol", bool ejecutarMetodoGuardar = false)
        {

            foreach (TableRow tb in tbCaptura.Rows)
                foreach (TableCell celda in tb.Cells)
                    foreach (Control ctrlWeb in celda.Controls)
                    {

                        if (ctrlWeb is UpdatePanel)
                        {
                            foreach (Control ctrl in (ctrlWeb as UpdatePanel).ContentTemplateContainer.Controls)
                            {

                                Comun.EjecutarMetodoObj(ctrlWeb, Constantes.NombreEventoControlAntes, ctrl, entidad);
                                RellenarEntidadWeb(ctrl, entidad, null, tag);
                                Comun.EjecutarMetodoObj(ctrlWeb, Constantes.NombreEventoControl, ctrl, entidad);
                            }
                        }
                        else
                        {

                            Comun.EjecutarMetodoObj(ctrlWeb, Constantes.NombreEventoControlAntes, ctrlWeb, entidad);
                            RellenarEntidadWeb(ctrlWeb, entidad, null, tag);
                            Comun.EjecutarMetodoObj(ctrlWeb, Constantes.NombreEventoControl, ctrlWeb, entidad);
                        }
                    }
        }

        /// <summary>
        /// Metodo que se encarga de asignar valores a una o varias propiedades de un control web, estos valores pueden ser especificados de la siguiente manera 'Text|10,Width|100'
        /// hay que tener en cuenta que si la propiedad es de complejo o es una clase, no se puede asignar el valor.
        /// </summary>
        /// <param name="ctrl">Control web al cual se le asginarán los valores.</param>
        /// <param name="valores">Cadena que contiene las propiedades y valores a asingar.</param>
        /// <param name="pagina">Pagina que contiene el control web.</param>
        public static void FijarValoresControl(Control ctrl, string valores, Page pagina)
        {
            if (string.IsNullOrWhiteSpace(valores))
                return;

            foreach (string valor in valores.Split(','))
            {
                
                string[] data = valor.Replace("$'", ",").Split('|');
                object valorDato = data[1];
                if (data[0] == "JSCRIPT")
                {
                    string valUID = string.Empty;
                    if (ctrl is WebControl)
                        valUID = (ctrl as WebControl).Attributes["uid"];
                    Utilerias.ExecScript(pagina, valorDato.ToString().Replace("{0}",valUID), "data_" + ctrl.ID);

                }
                else
                    if (data[0].IndexOf("*") == 0 && ctrl is WebControl)
                    {
                        (ctrl as WebControl).Attributes.Add(data[0].Replace("*", ""), valorDato.ToString());
                    }
                    else
                    {
                        if (Comun.EsDeTipo<int>(valorDato))
                            valorDato = Comun.Convertir<int>(valorDato);
                        Comun.FijarValorObjeto(ctrl, valorDato, data[0], false);
                    }
            }
        }

        /// <summary>
        /// Metodo que se encarga de configurar un componente web, de acuerdo a su capacidad maxima, estado.
        /// </summary>
        /// <param name="ncontrol">El control web a configurar.</param>
        /// <param name="infoCampo">Configuración del campo al cual esta enlazado el control web.</param>
        /// <param name="pagina">Pagina que contiene el control web.</param>
        /// <param name="esFiltro">Indica si el formulario que contiene el control web es un panel de filtro.</param>
        public void ConfigurarCampo(ref Control ncontrol, Cat_campo_tecnico infoCampo, Page pagina, bool esFiltro = true)
        {


            if (infoCampo.tamanio > 0)
                Comun.SetValorControlWeb(ncontrol, "MaxLength", infoCampo.tamanio);
            if (infoCampo.solo_lectura && !esFiltro)
            {
                if (!Comun.FijarValorObjeto(ncontrol, infoCampo.solo_lectura, "ReadOnly"))
                    Comun.FijarValorObjeto(ncontrol, !infoCampo.solo_lectura, "Enabled");
            }



            //Aqui se evalua la expresión del datasource para el componente
            if (!string.IsNullOrWhiteSpace(infoCampo.tipo.data_source) && !esFiltro)
            {
                object dsFinal = null;
                dsFinal = ObtenerFuenteDatosDLL(infoCampo, infoCampo.tipo.parametros, pagina, null, false);

                Comun.FijarValorObjeto(ncontrol, infoCampo.tipo.campo_valor, "DataValueField");
                Comun.FijarValorObjeto(ncontrol, infoCampo.tipo.campo_texto, "DataTextField");
                Comun.FijarValorObjeto(ncontrol, dsFinal, "DataSource", false);
                ncontrol.DataBind();

            }

            if (valoresDefault != null && valoresDefault.Keys.Contains(infoCampo.nombre))
                Comun.SetValorControlWeb(ncontrol, infoCampo.tipo_editor.propiedad_valor, valoresDefault[infoCampo.nombre]);

            ConfigurarControl(ncontrol, infoCampo);
            FijarValoresControl(ncontrol, infoCampo.tipo_editor.valores_propiedades, pagina);
        }

        /// <summary>
        /// Metodo encargado de crear and configurar un control web, de acuerdo a la configuración dinamica del campo.
        /// </summary>        
        /// <param name="ncontrol">El control que se desea configurar.</param>
        /// <param name="infoCampo">Información dinamica del campo a enlazar con el control.</param>
        /// <param name="ctrlCreados">Lista de los controles creados, esta lista es usada para enlazar controles web con dependencias, en el caso de DropDownList enlazados.</param>
        /// <param name="pagina">Pagina en la cual se va a dibujar el control web.</param>
        /// <param name="valoresDefault">Lista de valores por default configurados por el usuario, de aqui se toma el valor por default para el control web.</param>
        /// <returns>Control web configurado y lista para insertarse en la tabla dinamica.</returns>
        public Control CrearControlWeb(Control ncontrol, Cat_campo_tecnico infoCampo,
            Hashtable ctrlCreados, Page pagina, Dictionary<string, object> valoresDefault = null)
        {
            string id = infoCampo.nombre;
            UpdatePanel up = null;


            if (infoCampo.tamanio > 0)
                Comun.SetValorControlWeb(ncontrol, "MaxLength", infoCampo.tamanio);
            if (infoCampo.solo_lectura)
            {
                if (!Comun.FijarValorObjeto(ncontrol, infoCampo.solo_lectura, "ReadOnly"))
                    Comun.FijarValorObjeto(ncontrol, !infoCampo.solo_lectura, "Enabled");
            }

            if (ncontrol is WebControl)
                (ncontrol as WebControl).Attributes.Add("uid", "dg_cm_" + id);
            ncontrol.ID = contenedor + "|wcontrol|" + id;
            ncontrol.ClientIDMode = ClientIDMode.Static;
            ctrlCreados[id] = ncontrol;


            //Aqui se evalua la expresión del datasource para el componente
            if (!string.IsNullOrWhiteSpace(infoCampo.tipo.data_source))
            {
                object dsFinal = null;
                dsFinal = ObtenerFuenteDatosDLL(infoCampo, infoCampo.tipo.parametros, pagina, ctrlCreados);

                Comun.FijarValorObjeto(ncontrol, infoCampo.tipo.campo_valor, "DataValueField");
                Comun.FijarValorObjeto(ncontrol, infoCampo.tipo.campo_texto, "DataTextField");
                Comun.FijarValorObjeto(ncontrol, dsFinal, "DataSource", false);
                ncontrol.DataBind();

            }

            if (valoresDefault != null && valoresDefault.Keys.Contains(infoCampo.nombre))
                Comun.SetValorControlWeb(ncontrol, infoCampo.tipo_editor.propiedad_valor, valoresDefault[infoCampo.nombre]);

            if (!string.IsNullOrWhiteSpace(infoCampo.dependencia))
            {
                up = new UpdatePanel();
                up.ID = "up_" + id;
                up.ContentTemplateContainer.Controls.Add(ncontrol);
                up.UpdateMode = UpdatePanelUpdateMode.Conditional;

                foreach (string dp in infoCampo.dependencia.Split(','))
                {
                    string[] infodp = dp.Split('|');
                    //Aqui se crea un updatePanel para el control que va ser actualizado por la dependencia
                    if (ctrlCreados[infodp[0]] != null)
                    {
                        Comun.FijarValorObjeto(ctrlCreados[infodp[0]], true, "AutoPostBack");
                        (ctrlCreados[infodp[0]] as WebControl).Attributes.Add("onChange", "pkMsgModal('Actualizando datos..');");
                        up.Triggers.Add(new AsyncPostBackTrigger { ControlID = (ctrlCreados[infodp[0]] as Control).ID, EventName = infodp[1] });

                    }
                }
            }

            FijarValoresControl(ncontrol, infoCampo.tipo_editor.valores_propiedades, pagina);
            if (up == null)
            {
                return ncontrol;
            }
            else
                return up;

        }

        /// <summary>
        /// Metodo encargado de obtener el DataSource para un DropDownList, de acuerdo a la configuración dinamica configurada.
        /// </summary>
        /// <param name="datosCampo">Configuración dinamica del campo.</param>
        /// <param name="parametros">Lista de parametros asignados para la obtención de datos.</param>
        /// <param name="pagina">Pagina en la cual se va a dibujar el control web.</param>
        /// <param name="controlesCreados">Lista de controles creados, esta lista de usa para obtener los valores de aquellos controles enlazados.</param>
        /// <param name="configurarDependencias">Indica si se debe configurar las dependencias de un campo.</param>
        /// <returns>System.Object.</returns>
        public object ObtenerFuenteDatosDLL(Cat_campo_tecnico datosCampo, string parametros, Page pagina, Hashtable controlesCreados, bool configurarDependencias = true)
        {

            if (datosCampo.tipo.listado_fijo)
            {

                //Los datos para el componente son de una lista fija
                ArrayList dsFinal = new ArrayList();
                datosCampo.tipo.campo_valor = "valor";
                datosCampo.tipo.campo_texto = "texto";
                foreach (string val in datosCampo.tipo.data_source.Split(','))
                {
                    string[] info = val.Split('|');
                    (dsFinal as ArrayList).Add(new DatosClave { texto = info[0], valor = (info.Length > 1 ? info[1] : info[0]) });
                }
                return dsFinal;
            }

            //Aqui se obtiene el tipo de dato de la clase controlBase            
            string[] enumInfo = datosCampo.tipo.data_source.Split('|');
            string dll = enumInfo[0];
            string clase = enumInfo[1];
            string metodo = enumInfo[2];
            string propiedadValor = null;
            if (enumInfo.Length > 3)
                propiedadValor = enumInfo[3];
            string[] parametrosMetodo = null;
            if (!string.IsNullOrWhiteSpace(parametros))
                parametrosMetodo = parametros.Split(',');
            ArrayList parametrosUsuario = new ArrayList();
            Hashtable parametrosPOST = new Hashtable();
            ParameterInfo[] pmetodo;
            object tipo = null;

            if (!string.IsNullOrWhiteSpace(datosCampo.dependencia) && configurarDependencias)
            {
                foreach (string dependencia in datosCampo.dependencia.Split(','))
                {

                    string nombre = dependencia.Split('|')[0];
                    Control ctrlWeb = controlesCreados[nombre] as Control;
                    object valor = "";

                    if (pagina.IsPostBack || Entidad == null)
                        valor = pagina.Request[ctrlWeb.UniqueID];
                    else
                    {
                        valor = Entidad.ObtenerValor(nombre);
                    }

                    parametrosPOST[nombre] = valor;

                }
            }

            if (clase.Contains("="))
            {

                //Es un control generico
                List<Type> listaParametros = new List<Type>();
                string tiposParametros = clase.Split('=')[1];
                foreach (string tipos in tiposParametros.Split(','))
                {

                    listaParametros.Add(Comun.ObtenerTipoPorNombreEnsamblado(tipos));
                }
                tipo = Comun.CrearInstanciaGenerico(Comun.ObtenerTipoPorNombreEnsamblado(clase.Split('=')[0]), listaParametros.ToArray());

            }
            else
                tipo = Comun.ObtenerTipo(dll, clase);

            MethodInfo metodoTipo = tipo.GetType().GetMethod(metodo);
            pmetodo = metodoTipo.GetParameters();
            int x = 0;
            foreach (ParameterInfo dparametro in pmetodo)
            {
                object valorParametro = null;
                if (parametrosMetodo != null && parametrosMetodo.Length - 1 >= x && parametrosMetodo[x] != "-")
                {
                    valorParametro = Comun.Convertir(parametrosMetodo[x], dparametro.ParameterType);
                }
                else
                    valorParametro = dparametro.DefaultValue;

                if ((valorParametro == null || valorParametro.Equals(dparametro.DefaultValue)) && parametrosPOST.Count > 0)
                {
                    if (dparametro.ParameterType.IsClass)
                        valorParametro = Comun.CrearInstancia(dparametro.ParameterType.FullName);

                    if (valorParametro is TipoBase)
                        Comun.RellenarEntidad(parametrosPOST, valorParametro);
                    else if (parametrosPOST[dparametro.Name] != null)
                        valorParametro = Comun.Convertir(parametrosPOST[dparametro.Name], dparametro.ParameterType, dparametro.DefaultValue);
                }
                parametrosUsuario.Add(valorParametro);

                x++;
            }

            if (propiedadValor != null && propiedadValor.ToUpper() != "NULL")
            {
                metodoTipo.Invoke(tipo, parametrosUsuario.ToArray());
                return Comun.ObtenerValorPropiedad(tipo, propiedadValor);
            }
            else
                return metodoTipo.Invoke(tipo, parametrosUsuario.ToArray());



        }

        /// <summary>
        /// Metodo que se encarga de encontrar el control web personalizado por el usuario para la representación de los datos en el formulario.
        /// </summary>
        /// <param name="propiedad">Nombre del campo del cual se quiere obtener el control web personalizado, se lee el atributo 'campoFuente' del control web.</param>
        /// <param name="busqueda">Contenedor de los controles personalizados por el usuario.</param>
        /// <returns>Regresa null cuando no se encuentra el control web.</returns>
        private Control ObtenerControlPersonalizado(string propiedad, Control busqueda = null)
        {
            if (busqueda == null)
                busqueda = ObjetoPadre;
            if (busqueda == null)
                return null;

            foreach (Control ctrl in busqueda.Controls)
            {
                if (ctrl is WebControl && (ctrl as WebControl).Attributes["campoFuente"] != null && (ctrl as WebControl).Attributes["campoFuente"] == propiedad)
                    return ctrl;
                if (ctrl.HasControls())
                {
                    Control ctrlsub = ObtenerControlPersonalizado(propiedad, ctrl);
                    if (ctrlsub != null)
                        return ctrlsub;
                }
            }
            return null;

        }

        /// <summary>
        /// Configurar el estilo del control web a dibujar.
        /// </summary>
        /// <param name="ncontrol">El control web a configurar.</param>        
        /// <param name="datosUser">Configuración dinamica a aplicar.</param>        
        public void ConfigurarControl(Control ncontrol, Cat_campo_tecnico datosUser)
        {

            if (ncontrol is UpdatePanel)
            {
                foreach (Control subcontrol in (ncontrol as UpdatePanel).ContentTemplateContainer.Controls)
                    ConfigurarControl(subcontrol, datosUser);
                return;
            }

            string estilo = datosUser.tipo.estilo;


            if (estilo != null)
            {
                string[] infoEstilo = estilo.Split('|');
                if (ncontrol is UpdatePanel)
                {
                    foreach (Control ctrl in (ncontrol as UpdatePanel).ContentTemplateContainer.Controls)
                    {
                        Comun.FijarValorObjeto(ctrl, infoEstilo[infoEstilo.Length - 1], infoEstilo.Length > 1 ? infoEstilo[0] : "CssClass");
                    }
                }
                else
                    Comun.FijarValorObjeto(ncontrol, infoEstilo[infoEstilo.Length - 1], infoEstilo.Length > 1 ? infoEstilo[0] : "CssClass");
            }
            else
                Comun.FijarValorObjeto(ncontrol, "Edicion", "CssClass");




        }
        /// <summary>
        /// Configura el validador a un control web.
        /// </summary>
        /// <param name="rv">El control validador que se asigna al control web.</param>
        /// <param name="ncontrol">Control web, al cual se le configura el validador.</param>
        /// <param name="padre">Control web padre que contiene el control web, este control se usa para colocar el validador cerca del control.</param>
        public void AgregarValidador(Control rv, Control ncontrol, Control padre = null)
        {
            if (rv == null)
                return;
            if (padre == null)
                padre = ncontrol.Parent;
            if (rv != null)
            {
                if (ncontrol is UpdatePanel)
                    (ncontrol as UpdatePanel).ContentTemplateContainer.Controls.Add(rv);

                else
                    padre.Controls.Add(rv);
            }
        }
        /// <summary>
        /// Metodo que se encarga de crear el formulario de captura de un tipo de entidad especifico.
        /// </summary>
        /// <param name="tbCaptura">La tabla en la cual se dibujarán los controles web.</param>
        /// <param name="pagina">Pagina en la cual se va a dibujar el control web.</param>        
        /// <param name="dibujarTodosLosCampos">Indica si se deben mostrar todos los campo(true) o solo se deben mostrar los campos que fueron definidos por el usuario (false).</param>                
        /// <param name="soloLectura">Indica si el editor debe dibujar los validadores (false) o solo es un panel de visualización de datos (true)</param>
        /// <exception cref="System.Exception">No hay campos para editar, configure el tipo de dato...</exception>
        public void CrearPanelCaptura(Table tbCaptura, Page pagina, bool dibujarTodosLosCampos = true, bool soloLectura = false)
        {

            tbCaptura.Rows.Clear();
            TableRow filaHidden = new TableRow();

            TableCell celdaHidden = new TableCell();
            filaHidden.Cells.Add(celdaHidden);

            Hashtable ctrlCreados = new Hashtable();

            int campos = 0;
            var consultaCampos = from cp in camposDibujar orderby cp.orden ascending select cp;
            foreach (Cat_campo_tecnico datosUser in consultaCampos)
            {

                if (datosUser.editable)
                {
                    campos++;
                    string id = datosUser.nombre;
                    Control ncontrol = null;
                    RequiredFieldValidator rv = null;
                    LiteralControl lt = new LiteralControl();
                    Control ctrlUsuario = ObtenerControlPersonalizado(datosUser.nombre);
                    bool especificadoUsr = ctrlUsuario != null;
                    if (!soloLectura && especificadoUsr && ctrlUsuario is WebControl)
                    {
                        bool attrSoloLectura = Comun.Convertir<bool>((ctrlUsuario as WebControl).Attributes["data-SoloLectura"]);
                        soloLectura = soloLectura || (attrSoloLectura);
                    }
                    if ((especificadoUsr && !dibujarTodosLosCampos) || dibujarTodosLosCampos)
                    {


                        Control padreOriginal = especificadoUsr ? ctrlUsuario.Parent : null;
                        if (ctrlUsuario == null)
                        {
                            if (datosUser.tipo_editor.editor != null && datosUser.tipo_editor.editor.EndsWith(".ascx") && pagina != null)
                                ctrlUsuario = pagina.LoadControl(datosUser.tipo_editor.editor);
                            else
                            {
                                if (string.IsNullOrWhiteSpace(datosUser.tipo_editor.editor))
                                    ctrlUsuario = new TextBox();
                                else
                                {
                                    if (string.IsNullOrWhiteSpace(datosUser.tipo_editor.ensamblado))
                                        datosUser.tipo_editor.ensamblado = typeof(TextBox).Assembly.FullName;
                                    ctrlUsuario = (Control)Comun.ObtenerTipo(datosUser.tipo_editor.ensamblado, datosUser.tipo_editor.editor);
                                }


                            }
                        }


                        ncontrol = CrearControlWeb(ctrlUsuario, datosUser, ctrlCreados, pagina, valoresDefault);
                        CustomValidator cv = null;
                        if (!soloLectura)
                        {
                            cv = Utilerias.FijarValidacionRegex(pagina, ncontrol, datosUser.nombre, datosUser.tipo.regex_validacion, datosUser.tipo.texto_regex, datosUser.titulo);
                            ConfigurarControl(ncontrol, datosUser);
                        }

                        if (datosUser.requerido && !soloLectura)
                        {
                            lt.Text = "* ";
                            rv = new RequiredFieldValidator();
                            rv.ControlToValidate = ncontrol.ID;
                            rv.SetFocusOnError = true;
                            rv.ValidationGroup = "validacionEntidad";
                            rv.EnableClientScript = false;
                            rv.CssClass = "errorValidador";
                            rv.Display = ValidatorDisplay.Dynamic;
                            rv.Text = "El campo " + datosUser.titulo + " es requerido<br />";
                        }

                        if (!string.IsNullOrWhiteSpace(datosUser.comentario) && !soloLectura)
                        {

                            string[] dtCom = datosUser.comentario.Split(':');
                            if (dtCom.Length > 1)
                                lt.Text += string.Format("<span class='{0}'>{1}</span>", dtCom[0], dtCom[1]);
                            else
                                lt.Text += datosUser.comentario;
                        }
                        lt.Text = "<span class='Comentario'>" + lt.Text + "</span>";

                        if (especificadoUsr)
                        {
                            ctrlUsuario.Parent.Controls.Add(lt);
                            AgregarValidador(cv, ctrlUsuario);
                            AgregarValidador(rv, ctrlUsuario);

                        }
                        else
                        {
                            if (!(ncontrol is HiddenField))
                            {

                                TableRow nfila = CrearFIla(id);
                                nfila.Cells.Add(CrearCelda("titulo_" + id, datosUser.titulo));
                                nfila.Cells.Add(CrearCelda("dato_" + id, ncontrol));
                                nfila.Cells.Add(CrearCelda("comentario_" + id, lt));
                                tbCaptura.Rows.Add(nfila);

                                AgregarValidador(cv, ncontrol, tbCaptura.Parent);
                                AgregarValidador(rv, ncontrol, tbCaptura.Parent);


                            }
                            else
                                celdaHidden.Controls.Add(ncontrol);
                        }


                    }//Fin del if

                }
            }
            tbCaptura.Rows.Add(filaHidden);
            if (campos == 0)
                throw new Exception("No hay campos para editar, configure el tipo de dato...");
        }



        /// <summary>
        /// Metodo que crea una nueva fila de una tabla.
        /// </summary>
        /// <param name="id">Id para la fila.</param>
        /// <returns>Nueva fila</returns>
        public static TableRow CrearFIla(string id)
        {
            TableRow ntbrow = new TableRow();
            ntbrow.ID = "tb_" + id;
            return ntbrow;
        }

        /// <summary>
        /// Crea una celda de una tabla
        /// </summary>
        /// <param name="id">Id de la celda</param>
        /// <param name="dato">El dato a escribir en la celda, puede ser string o un control web.</param>
        /// <returns>Celda de una tabla.</returns>
        public static TableCell CrearCelda(string id, object dato = null)
        {

            TableCell ncelda = new TableCell();
            ncelda.ID = "celda_" + id;
            if (dato != null)
            {
                if (dato is string)
                {
                    ncelda.CssClass = "LabelCampos";
                    ncelda.Text = dato.ToString();
                }
                else
                {

                    ncelda.Controls.Add(dato as Control);


                }

            }
            return ncelda;
        }
    }
}
